﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VBOX
{
    class VboxSocket
    {
        //申明委托类型
        public delegate void UpdateTextEventHandler(byte[] revText);
        //使用委托类型申明委托函数
        public UpdateTextEventHandler updateTextBox;

        private int _port;
        private IPAddress _IpAddress;
        Socket client = null; //客户端
        Socket server = null; //服务器accept
        Socket tSocket = null; //服务器单一服务
        Thread thread_recv_client = null;
        Thread thread_recv_server = null;
        Thread thread_accept = null;

        public int SocketTxByte = 0;
        public int SocketRxByte = 0;

        public VboxSocket(string ip, string port)
        {
            _IpAddress = IPAddress.Parse(ip);
            _port = Convert.ToInt32(port);
        }

        public bool Open(ComboBox info, ComboBox mode)
        {
            

            if (mode.Text == "tcp_client")
            {
                try
                {
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPEndPoint point = new IPEndPoint(_IpAddress, _port);
                    client.Connect(point);
                    info.Text = client.LocalEndPoint.ToString();
                    thread_recv_client = new Thread(ReceiveMsg);
                    thread_recv_client.IsBackground = true;
                    thread_recv_client.Start(client);
                }
                catch
                {
                    MessageBox.Show("socket创建失败");
                    return false;
                }
            }
            else 
            {
                try
                {
                    server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPEndPoint point = new IPEndPoint(_IpAddress, _port);
                    server.Bind(point);
                    server.Listen(1);
                    thread_accept = new Thread(AcceptInfo);
                    thread_accept.IsBackground = true;
                    thread_accept.Start(server);
                }
                catch
                {
                    MessageBox.Show("socket绑定失败");
                }
            }

            return true;
        }

        private void AcceptInfo(object o)
        {
            Socket socket = o as Socket;

            while (true)
            {
                try
                {
                    tSocket = socket.Accept();
                    string point = tSocket.RemoteEndPoint.ToString();

                    if (thread_recv_server == null)
                    {
                        thread_recv_server = new Thread(ReceiveMsg);
                        thread_recv_server.IsBackground = true;
                        thread_recv_server.Start(tSocket);
                    }
                    
                }
                catch
                {
                    return;
                }
            }
        }

        public bool Close(ComboBox mode)
        {
            try
            {
                if (mode.Text == "tcp_client")
                {
                    client.Close();
                    thread_recv_client.Abort();
                    client.Dispose();
                }

                if (mode.Text == "tcp_server")
                {
                    server.Close();
                    thread_accept.Abort();
                    server.Dispose();
                    thread_recv_server.Abort();
                }

            }
            catch
            {
                MessageBox.Show("socket关闭失败");
                return false;
            }
            return true;
        }

        private void ReceiveMsg(object o)
        {
            Socket rSocket = o as Socket;

            int recv_len = 0;
            byte[] buffer = new byte[1024 * 1024];

            while (true)
            {
                try
                {
                    recv_len = rSocket.Receive(buffer);
                    if (recv_len > 0)
                    {
                        byte[] RecvData = new byte[recv_len];
                        Array.Copy(buffer, RecvData, recv_len);
                        updateTextBox(RecvData);
                    }
                }
                catch
                {
                    MessageBox.Show("远程服务已关闭！");
                    return;
                }
            }
        }

        public void SendDataByString(ComboBox obj, string data)
        {
            try
            {
                byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(data);
                int length = bytes.Length;

                SocketTxByte += length;

                if (obj.Text == "tcp_server")
                {
                    tSocket.Send(bytes);
                }
                if (obj.Text == "tcp_client")
                {
                    client.Send(bytes);
                }

            }
            catch (Exception)
            {
                MessageBox.Show("链接已断开");
            }
        }

        public void SendDataByHex(ComboBox obj, string str)
        {
            string print_str = str;
            string[] strArray = str.Split(new char[] { ' ' });
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < strArray.Length; i++)
            {
                builder.Append(strArray[i]);
            }
            str = builder.ToString();
            if ((str.Length % 2) != 0)
            {
                str = str.Insert(str.Length - 1, "0");
            }
            byte[] buffer = new byte[str.Length / 2];

            for (int j = 0; j < (str.Length / 2); j++)
            {
                try
                {
                    buffer[j] = Convert.ToByte(str.Substring(j * 2, 2), 0x10);
                }
                catch
                {
                    //停止循环发送 防止无限弹窗
                    //checkBoxLoopSend.Checked = false;
                    MessageBox.Show("包含非16进制字符，发送失败！", "提示");
                    return;
                }
            }

            try
            {
                SocketTxByte += buffer.Length;

                string print_time = DateTime.Now.ToString("HH:mm:ss.fff");

                client.Send(buffer);
            }
            catch (Exception)
            {
                MessageBox.Show("发送数据时发生错误, 串口将被关闭！", "错误提示");
            }
        }
    }
}
